package fr.bugtracker.dao.technique;

import java.util.List;

import javax.ejb.Stateless;

import org.apache.lucene.search.Query;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.hibernate.transform.Transformers;

import fr.bugtracker.commun.dto.DtoInformationCompte;
import fr.bugtracker.commun.dto.DtoRetourPagination;
import fr.bugtracker.commun.exception.ExceptionFonctionnelle;
import fr.bugtracker.commun.outils.UtilsHibernate;
import fr.bugtracker.entity.technique.Utilisateur;

/**
 * Session bean fr.bugtracker.dao pour les utilisateurs
 * @author lparrot
 */
@Stateless
public class DaoUtilisateur extends DaoAbstract<Utilisateur> {

	/**
	 * Constructeur de la classe <code>DaoUtilisateur</code>.
	 */
	public DaoUtilisateur() {
	}

	/**
	 * liste les utilisateurs en effectuant la recherche
	 * @return {@link List}< {@link Utilisateur} >
	 */
	public List<Utilisateur> listerUtilisateurByRecherche() {
		Session session = UtilsHibernate.getSession();
		FullTextSession fullTextSession = Search.getFullTextSession(session);
		QueryBuilder builder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Utilisateur.class).get();
		Query luceneQuery = builder.keyword().onField("username").matching("kestounet@gmail.com").createQuery();
		return fullTextSession.createFullTextQuery(luceneQuery).list();
	}

	/**
	 * Controle l'unicité du nom d'utilisateur en
	 * @param username {@link String}
	 * @throws ExceptionFonctionnelle -
	 */
	public void controlerUniciteUsername(String username) throws ExceptionFonctionnelle {
		int nombreCompte = ((Long) UtilsHibernate.getSession().createCriteria(Utilisateur.class).add(Restrictions.eq("username", username)).setProjection(Projections.count("id")).uniqueResult()).intValue();
		if (nombreCompte > 1) {
			throw new ExceptionFonctionnelle("fonctionnel.exception.non_unique_result_exception", "Controle d'unicité sur le nom d'utilisateur");
		}
		if (nombreCompte == 1) {
			throw new ExceptionFonctionnelle("fonctionnel.utilisateur.erreur.unicite", username);
		}
	}

	/**
	 * Retourne la liste des utilisateurs dont le compte est en attente de validation
	 * @return {@link List}< {@link Utilisateur} >
	 */
	public List<Utilisateur> getAllUtilisateurValidationCompteEnAttente() {
		return UtilsHibernate.getSession().createCriteria(Utilisateur.class).add(Restrictions.eq("enAttenteValidation", true)).list();
	}

	/**
	 * Récupère l'utilisateur par rapport à son login
	 * @param username {@link String} le login de l'utilisateur
	 * @return {@link Utilisateur}
	 * @throws ExceptionFonctionnelle -
	 */
	public Utilisateur getUtilisateurByUsername(String username) throws ExceptionFonctionnelle {
		Session session = UtilsHibernate.getSession();
		return (Utilisateur) session.createCriteria(Utilisateur.class).add(Restrictions.eq("username", username)).uniqueResult();
	}

	/**
	 * Retourne les informations sur le compte utilisateur pour l'affichage
	 * @param idUtilisateur int
	 * @return {@link DtoInformationCompte}
	 */
	public DtoInformationCompte getInformationCompteByIdUtilisateur(int idUtilisateur) {
		Session session = UtilsHibernate.getSession();
		Criteria criteria = session.createCriteria(Utilisateur.class, "uti").createAlias("profil", "pfl").createAlias("compte", "cpt").createAlias("information", "ifn");
		ProjectionList projections = Projections.projectionList().add(Projections.property("uti.username")).add(Projections.property("pfl.libelle")).add(Projections.property("cpt.theme"))
				.add(Projections.property("ifn.nom")).add(Projections.property("ifn.prenom")).add(Projections.property("ifn.numeroTelephone")).add(Projections.property("ifn.numeroPortable"))
				.add(Projections.property("uti.dateCreation"));
		criteria.setProjection(projections).add(Restrictions.eq("uti.id", idUtilisateur));
		return (DtoInformationCompte) criteria.setResultTransformer(Transformers.aliasToBean(DtoInformationCompte.class)).uniqueResult();
	}

	/**
	 * Retourne les utilisateurs dont la date de suppression est vide
	 * @param first int
	 * @param pageSize int
	 * @param sortField {@link String}
	 * @param sortOrder {@link String}
	 * @param typeRecherche {@link Boolean}
	 * @return {@link DtoRetourPagination}
	 */
	public DtoRetourPagination rechercherUtilisateur(int first, int pageSize, String sortField, String sortOrder, boolean typeRecherche) {
		Session session = UtilsHibernate.getSession();
		Criteria criteria = session.createCriteria(Utilisateur.class);
		if (typeRecherche) {
			criteria.add(Restrictions.isNull("dateSuppression"));
		} else {
			criteria.add(Restrictions.isNotNull("dateSuppression"));
		}
		return findByPagination(first, pageSize, sortField, sortOrder, criteria);
	}

}
